'''
作者：董震
功能：摄像头实时人脸模糊处理
依赖库：opencv-python（图像处理）、mediapipe（人脸识别）
使用说明：
1. 安装依赖：pip install opencv-python mediapipe
2. 运行代码，自动打开摄像头（0=内置摄像头，外接摄像头改为1/2等）
3. 实时模糊检测到的人脸，按Q键退出程序
'''
import cv2
import mediapipe as mp

# 初始化默认摄像头（0为内置摄像头，外接摄像头可改为1、2等）
cap = cv2.VideoCapture(0)
# 加载MediaPipe人脸检测模块
mp_face_detection = mp.solutions.face_detection

# 配置人脸检测模型并创建实例
# model_selection=0：近距离检测（适配摄像头场景）
# min_detection_confidence=0.5：置信度阈值，过滤低可信度检测结果
with mp_face_detection.FaceDetection(
        model_selection=0,
        min_detection_confidence=0.5) as face_detection:

    # 循环读取摄像头视频流
    while cap.isOpened():
        # 读取单帧画面：ret为读取成功标识，img为当前帧图像
        ret, img = cap.read()
        # 若读取失败（如摄像头断开），打印提示并退出循环
        if not ret:
            print("❌ 无法读取摄像头画面，退出程序")
            break

        # 将BGR格式图像转为RGB（MediaPipe要求输入为RGB格式）
        img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        # 执行人脸检测，返回检测结果
        results = face_detection.process(img_rgb)

        # 若检测到人脸，遍历所有检测结果
        if results.detections:
            # 获取当前帧图像的高度和宽度（用于坐标边界限制）
            img_h, img_w = img.shape[:2]
            for detection in results.detections:
                # 获取人脸边界框的相对坐标数据（0~1范围）
                bbox = detection.location_data.relative_bounding_box

                # 计算原始人脸框的左上、右下顶点像素坐标
                # 先提取bbox的核心参数（语义化命名，避免重复写bbox.xxx）
                face_x_ratio = bbox.xmin  # 人脸左上角x坐标（相对画面宽度的比例）
                face_y_ratio = bbox.ymin  # 人脸左上角y坐标（相对画面高度的比例）
                face_w_ratio = bbox.width  # 人脸宽度（相对画面宽度的比例）
                face_h_ratio = bbox.height  # 人脸高度（相对画面高度的比例）
                #像素坐标
                x1 = int(face_x_ratio * img_w)  # 人脸左上x（像素）
                y1 = int(face_y_ratio * img_h)  # 人脸左上y（像素）
                x2 = int((face_x_ratio + face_w_ratio) * img_w)  # 人脸右下x（像素）
                y2 = int((face_y_ratio + face_h_ratio) * img_h)  # 人脸右下y（像素）

                # 定义边界框扩大幅度（单位：像素）
                expand = 5
                x1 = max(0, x1 - expand)          # 左上x -去扩张表示向左移动
                y1 = max(0, y1 - expand)          # 左上y -去扩张表示向上移动
                x2 = min(img_w, x2 + expand)      # 右下x +上扩张表示向右移动
                y2 = min(img_h, y2 + expand)      # 右下y +上扩张表示向下移动

                # 对矩形框内区域进行模糊处理
                # 人脸区域均值模糊（核50x50，重度模糊）
                img[y1:y2, x1:x2] = cv2.blur(img[y1:y2, x1:x2], (50, 50))
                # 中值模糊，核的大小必须是基数
                # img[y1:y2, x1:x2] = cv2.medianBlur(img[y1:y2, x1:x2], 15)
                # 高斯模糊，核的大小必须是基数
                # img[y1:y2, x1:x2] = cv2.GaussianBlur(img[y1:y2, x1:x2], (49, 49), 0)     # 选取图像中人脸位置，并做模糊处理

        # 显示处理后的视频画面
        cv2.imshow('Face Blur Result (Press Q to Exit)', img)

        # 按键检测：按Q键（ord('q')获取Q的ASCII码）退出程序
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

# 释放摄像头资源（避免摄像头被占用）
cap.release()
# 关闭所有OpenCV创建的窗口
cv2.destroyAllWindows()